from win32gui import GetWindowTextLength

from Data import search_file
from docx import Document
import win32com.client
import os
import openpyxl
from openpyxl.styles import Alignment

yichang = False
result_path = None
title_number = None
results_number = None
first_table_number = None


def check_tables_between_titles(doc, titles):
    """检查每两个标题之间的表格数量"""
    try:
        # 获取所有表格
        tables = list(doc.Tables)
        if not tables or len(tables) <= 1:
            print("表格数量不足，跳过检查")
            return

        print("-" * 50)
        print(f"\n开始检查表格数量，共有标题 {len(titles)} 个")
        # 获取每个标题的位置
        title_positions = []
        selection = doc.Application.Selection
        selection.HomeKey(Unit=6)  # 移动到文档开始

        # 直接查找titles列表中每个标题的位置
        for title in titles:
            selection.HomeKey(Unit=6)  # 每次查找前都回到文档开始
            selection.Find.ClearFormatting()
            selection.Find.Style = doc.Styles("标题 2")
            selection.Find.Text = title
            selection.Find.Forward = True
            selection.Find.MatchCase = True
            selection.Find.MatchWholeWord = True

            found = selection.Find.Execute()
            if found:
                title_positions.append(selection.Start)
                # print(f"找到标题 '{title}' 位置: {selection.Start}")
            else:
                print(f"警告：未找到标题 '{title}' 的位置")

        if not title_positions:
            print("未找到任何标题位置，退出检查")
            return

        # 添加文档末尾位置
        title_positions.append(doc.Content.End)
        # print(f"文档末尾位置: {doc.Content.End}")

        # 统计每两个标题之间的表格数量
        for i in range(len(titles)):
            start_pos = title_positions[i]
            # 找到下一个不同的标题位置
            next_pos = None
            for j in range(i + 1, len(title_positions)):
                if title_positions[j] > start_pos:
                    next_pos = title_positions[j]
                    break

            if next_pos is None:
                next_pos = doc.Content.End

            # print(f"DEBUG - 标题位置: {start_pos}, 下一个标题位置: {next_pos}")
            table_count = 0

            # 计算在这个范围内的表格数量
            for table in tables:
                table_start = table.Range.Start
                # 表格必须在当前标题之后，且在下一个标题之前
                if start_pos < table_start < next_pos:
                    table_count += 1
                    # print(f"DEBUG - 标题 '{titles[i]}' 找到表格，位置: {table_start}")

            # 如果表格数量不是1，输出警告
            if table_count != 1:
                print(f"\033[93m警告：{titles[i]} 包含 {table_count} 个表格\033[0m")

    except Exception as e:
        print(f"\033[91m检查表格数量时出错：{str(e)}\033[0m")


def process_ecc_document(doc):
    """处理 ECC 文档的特殊结构，返回标题和内容"""
    titles = []
    results = []
    first_table_data = []

    try:
        selection = doc.Application.Selection
        selection.HomeKey(Unit=6)  # 移动到文档开始

        # 获取所有标题 2
        while True:
            selection.Find.ClearFormatting()
            selection.Find.Style = doc.Styles("标题 2")
            found = selection.Find.Execute(Forward=True)

            if not found:
                break

            title_text = selection.Text.strip()
            if title_text and not title_text.isspace():
                if "命令标识符表" != title_text:
                    titles.append(title_text)

            selection.Collapse(0)
            selection.MoveRight(Unit=1, Count=1)
            selection.Collapse(1)

        # 获取所有表格第一行内容
        tables = list(doc.Tables)
        for table in tables:
            if table.Rows.Count > 0:
                # 检查是否为命令作用表（第一行是否包含"命令"和"作用"）
                if table.Columns.Count >= 2:
                    first_command = table.Cell(1, 1).Range.Text.strip().replace('\r', '').replace('\x07', '')
                    first_action = table.Cell(1, 2).Range.Text.strip().replace('\r', '').replace('\x07', '')

                    if first_command == "命令" and first_action == "作用":
                        # 处理命令作用表
                        for i in range(2, table.Rows.Count + 1):
                            command = table.Cell(i, 1).Range.Text.strip().replace('\r', '').replace('\x07', '')
                            action = table.Cell(i, 2).Range.Text.strip().replace('\r', '').replace('\x07', '')
                            if command:
                                first_table_data.append((command, action))
                    else:
                        # 获取非命令作用表的第一行内容
                        cell_text = table.Cell(1, 2).Range.Text.strip()
                        first_line = cell_text.split('\r')[0].strip()
                        if first_line and not first_line.isspace() and "含义" != first_line:
                            results.append(first_line)

    except Exception as e:
        print(f"\033[91m处理ECC文档时出错：{str(e)}\033[0m")

    return results, titles, first_table_data


# 在 txt 函数中修改 ECC 文档的处理部分
def txt(doc_path):
    global title_number
    global results_number
    global first_table_number
    word = None
    doc = None
    global yichang
    try:
        word = win32com.client.Dispatch("Word.Application")
        word.Visible = True
        doc = word.Documents.Open(os.path.abspath(doc_path))

        # 判断是否为 ECC 文档
        if "ECC" in os.path.basename(doc_path):
            results, titles, first_table_data = process_ecc_document(doc)
            if titles and doc.Tables:
                check_tables_between_titles(doc, titles)
            return results, titles, first_table_data
        else:
            # 原有的处理逻辑保持不变
            results = []
            titles = []

        # 1. 先获取所有标题2
        selection = word.Selection
        selection.HomeKey(Unit=6)  # 移动到文档开始

        while True:
            selection.Find.ClearFormatting()
            selection.Find.Style = doc.Styles("标题 2")
            found = selection.Find.Execute(Forward=True)

            if not found:
                break

            text = selection.Text.strip()
            if text and not text.isspace():  # 移除 last_text 的判断，允许重复标题
                if "命令标识符表" == text:
                    continue
                else:
                    titles.append(text)

            selection.Collapse(0)
            selection.MoveRight(Unit=1, Count=1)
            selection.Collapse(1)
        # print(titles)
        # 2. 获取从第二个表格开始的所有表格第一行内容
        tables = list(doc.Tables)
        results = []
        last_table_content = None  # 记录上一个表格的内容
        seen_contents = set()  # 移到外层，确保整个处理过程都使用同一个集合

        if len(tables) > 1:
            for table in tables[1:]:
                try:
                    if table.Rows.Count > 0 and table.Columns.Count >= 2:
                        cell_text = table.Cell(1, 2).Range.Text.strip()

                        # 如果发现短横线，输出上一个表格的内容警告信息
                        if cell_text in ['-\r\x07', '-', '\r\x07']:
                            if last_table_content:
                                print(f"\033[91m警告：{last_table_content}\033[0m所在表格被拆分，请检查其完整性")
                            continue

                        first_line = cell_text.split('\r')[0].strip()
                        if first_line and not first_line.isspace() and any(
                                '\u4e00' <= char <= '\u9fff' for char in first_line):
                            # 跳过包含"含义"的内容
                            if "含义" == first_line:
                                continue

                            # PACP文档特殊处理：检查重复内容
                            if "PCAP" in os.path.basename(doc_path):
                                # 更严格的规范化处理
                                normalized_line = ''.join(first_line.split())  # 移除所有空白字符
                                if normalized_line not in seen_contents:
                                    results.append(first_line)
                                    results = list(dict.fromkeys(results))
                                    # seen_contents.add(normalized_line)
                                    # print(f'results:{results}')
                            else:
                                results.append(first_line)
                                # print(f'results:{results}')

                            # 记录当前表格第一行第二列的内容作为上一个表格内容
                            last_table_content = table.Cell(1, 2).Range.Text.strip().split('\r')[0].strip()
                except:
                    continue
        # print(f'results:{results}')

        # 3. 获取第一个表格的命令和作用，用于后续比对
        first_table_data = []
        if tables:
            first_table = tables[0]
            if first_table.Rows.Count > 0:
                # 检查第一行是否为标题行
                first_command = first_table.Cell(1, 1).Range.Text.strip().replace('\r', '').replace('\x07', '')
                first_action = first_table.Cell(1, 2).Range.Text.strip().replace('\r', '').replace('\x07', '')

                if first_command == "命令" and first_action == "作用":
                    # 如果是标题行，从第二行开始遍历
                    start_row = 2
                else:
                    # 如果不是标题行，从第一行开始遍历
                    start_row = 1

                if first_command != "命令" or first_action != "作用":
                    yichang = True
                    print(f"\033[91m命令摘要表格异常：{os.path.basename(doc_path).rsplit('.', 1)[0]}\033[0m")
                    return [], [], []

                for i in range(start_row, first_table.Rows.Count + 1):
                    command = first_table.Cell(i, 1).Range.Text.strip().replace('\r', '').replace('\x07', '')
                    action = first_table.Cell(i, 2).Range.Text.strip().replace('\r', '').replace('\x07', '')
                    if command:  # 只要命令不为空就保存，不管作用是否为空
                        first_table_data.append((command, action))
        # 在获取完标题和表格后，调用检查函数
        if titles and tables:
            check_tables_between_titles(doc, titles)

        # 修改标题和描述数量的统计逻辑
        if len(titles) != len(results):
            print(f"\033[91m标题与命令描述获取数量不符，请注意\033[0m")
            print(f"标题数量：{len(titles)}")
            title_number = len(titles)
            print(f"命令描述数量：{len(results)}")
            results_number = len(results)

        # 移除这部分代码，不再自动补齐
        # max_len = max(len(titles), len(results))
        # titles.extend([''] * (max_len - len(titles)))
        # results.extend([''] * (max_len - len(results)))

        if len(titles) != len(first_table_data):
            print(f"\033[91m标题与命令摘要表格数量不符，请注意\033[0m")
            print(f"标题数量：{len(titles)}")
            title_number = len(titles)
            print(f"命令表格数量：{len(first_table_data)}")
            first_table_number = len(first_table_data)
        # print(first_table_data)
        if results_number is None:
            results_number = title_number
        if first_table_number is None:
            first_table_number = title_number
        return results, titles, first_table_data

    except Exception as e:
        print(f"发生错误: {str(e)}")
        import traceback
        print(traceback.format_exc())
        return [], [], []
    finally:
        try:
            if doc:
                doc.Close(SaveChanges=False)
            if word:
                word.Quit()
        except:
            pass


def write_to_excel(titles, contents, doc_path, is_folder=True):
    global title_number
    global results_number
    global first_table_number
    # 创建新的Excel工作簿
    wb = openpyxl.Workbook()

    # 重命名第一个工作表
    ws = wb.active
    ws.title = "命令描述"

    # 设置列宽
    ws.column_dimensions['A'].width = 30
    ws.column_dimensions['B'].width = 50

    # 写入数据（使用最大长度确保所有数据都被写入）
    max_length = max(len(titles), len(contents))
    current_row = 1  # 使用独立的行计数器

    # 记录写入的行数
    written_rows = 0

    # 修改写入逻辑，确保所有内容都能写入
    current_row = 1
    written_rows = 0

    # 先写入所有标题和对应的内容
    for i in range(len(titles)):
        if titles[i] != "命令标识符表":
            ws.cell(row=current_row, column=1, value=titles[i])
            ws.cell(row=current_row, column=1).alignment = Alignment(wrapText=True, vertical='center')

            # 如果有对应的内容就写入
            if i < len(contents):
                content = contents[i]
                if content and content.strip():
                    ws.cell(row=current_row, column=2, value=content)
                    ws.cell(row=current_row, column=2).alignment = Alignment(wrapText=True, vertical='center')
            else:
                ws.cell(row=current_row, column=2, value="")
                ws.cell(row=current_row, column=2).alignment = Alignment(wrapText=True, vertical='center')

            current_row += 1
            written_rows += 1

    # 写入剩余的内容（如果内容比标题多）
    for i in range(len(titles), len(contents)):
        content = contents[i]
        if content and content.strip():
            ws.cell(row=current_row, column=2, value=content)
            ws.cell(row=current_row, column=2).alignment = Alignment(wrapText=True, vertical='center')
            current_row += 1
            written_rows += 1

    # 在保存前打印实际写入的行数
    print(f"实际写入行数：{written_rows}")

    # 根据文档路径生成Excel保存路径
    doc_dir = os.path.dirname(doc_path)
    doc_name = os.path.splitext(os.path.basename(doc_path))[0]

    if not is_folder:
        # 单文件模式：保存在Word文档所在目录
        excel_path = os.path.join(doc_dir, f"{doc_name}.xlsx")
    else:
        # 文件夹模式：在父目录创建新目录结构
        parent_dir = os.path.dirname(os.path.dirname(doc_dir))  # 获取父目录
        current_dir_name = os.path.basename(os.path.dirname(doc_dir))  # 获取当前目录名

        # 创建新的目标目录
        target_base_dir = os.path.join(parent_dir, f"{current_dir_name}-检查结果")
        # 保持原有的子目录结构
        relative_path = os.path.relpath(doc_path, os.path.dirname(doc_dir))
        target_dir = os.path.join(target_base_dir, os.path.dirname(relative_path))

        os.makedirs(target_dir, exist_ok=True)
        excel_path = os.path.join(target_dir, f"{doc_name}.xlsx")

    # 保存文件
    wb.save(excel_path)
    print(f"Excel文件已保存: {excel_path}")
    print("-" * 50)


def table(is_folder, export_excel):
    if is_folder:
        filepaths = search_file.select_folder()
    else:
        filepaths = search_file.select_file()
    if filepaths == "-1":
        return "-1"
    print("开始比对命令作用：")
    print("-" * 50)

    # 每次开始新的处理时重置命令使用记录
    if hasattr(find_command_action, 'used_rows'):
        find_command_action.used_rows = {}

    # 如果需要导出Excel，创建比对结果工作簿
    # 在 table 函数中，修改相关部分
    if export_excel:
        result_wb = openpyxl.Workbook()
        result_ws = result_wb.active
        result_ws.title = "命令比对"

        # 设置表头
        headers = ['文档', '命令', '文档描述', '表格描述']
        for col, header in enumerate(headers, 1):
            result_ws.cell(row=1, column=col, value=header)
            result_ws.cell(row=1, column=col).alignment = Alignment(horizontal='center')

        # 设置列宽
        result_ws.column_dimensions['A'].width = 50
        result_ws.column_dimensions['B'].width = 30
        result_ws.column_dimensions['C'].width = 50
        result_ws.column_dimensions['D'].width = 50

        # 创建统计页签
        stats_ws = result_wb.create_sheet("数量统计")
        stats_ws.column_dimensions['A'].width = 80  # 文档路径较长
        stats_ws.column_dimensions['B'].width = 15
        stats_ws.column_dimensions['C'].width = 15
        stats_ws.column_dimensions['D'].width = 15

        # 写入统计表头
        stats_headers = ["文档", "标题数", "描述数", "表格数"]
        for col, header in enumerate(stats_headers, 1):
            stats_ws.cell(row=1, column=col, value=header)
            stats_ws.cell(row=1, column=col).alignment = Alignment(horizontal='center')

        stats_row = 2  # 从第二行开始写入统计数据
        row_index = 2  # 从第二行开始写入比对数据

    global result_path
    for filepath in filepaths:
        # 重置异常状态和命令使用记录
        global yichang, title_number, results_number, first_table_number
        yichang = False
        title_number = None
        results_number = None
        first_table_number = None
        if hasattr(find_command_action, 'used_rows'):
            find_command_action.used_rows = {}

        # 检查文件类型
        file_ext = os.path.splitext(filepath)[1].lower()
        if file_ext not in ['.doc', '.docx']:
            continue

        # 检查是否为扉页文件
        filename = filepath.split('\\')[-1] if '\\' in filepath else filepath.split('/')[-1]
        if "扉页" in filename:
            continue

        if "~" in filepath:  # 跳过临时文件
            continue

        try:
            filename_new = filename.rsplit('.', 1)[0]
            if is_folder:
                parent_dir = os.path.basename(os.path.dirname(filepath))
                print(f"正在处理文件：\033[95m{parent_dir}->{filename_new}\033[0m")
                if "ACL" in filename_new:
                    print(f"\033[95m{filename_new}->建议手工check\033[0m")
            else:
                parent_dir = os.path.basename(os.path.dirname(filepath))
                print(f"正在处理文件：\033[95m{parent_dir}->{filename_new}\033[0m")
                if "ACL" in filename_new:
                    print(f"\033[95m{filename_new}->建议手工check\033[0m")

            text, titles, first_table_data = txt(filepath)

            # 生成Excel路径
            doc_dir = os.path.dirname(filepath)
            doc_name = os.path.splitext(os.path.basename(filepath))[0]

            if is_folder:
                # 文件夹模式：在父目录创建新目录结构
                parent_dir = os.path.dirname(os.path.dirname(doc_dir))  # 获取父目录
                current_dir_name = os.path.basename(os.path.dirname(doc_dir))  # 获取当前目录名
                target_base_dir = os.path.join(parent_dir, f"{current_dir_name}-检查结果")
                # 保持原有的子目录结构
                relative_path = os.path.relpath(filepath, os.path.dirname(doc_dir))
                target_dir = os.path.join(target_base_dir, os.path.dirname(relative_path))
                excel_path = os.path.join(target_dir, f"{doc_name}.xlsx")
            else:
                # 单文件模式：保存在Word文档所在目录
                excel_path = os.path.join(doc_dir, f"{doc_name}.xlsx")

            # 写入Excel
            if yichang:
                continue
            else:
                write_to_excel(titles, text, filepath, is_folder)
                # 写入统计数据到命令比对结果文件
                if export_excel:
                    # 只有当至少有一个参数不为None时才写入统计数据
                    if any(x is not None for x in [title_number, results_number, first_table_number]):
                        stats_ws.cell(row=stats_row, column=1, value=filepath)
                        stats_ws.cell(row=stats_row, column=2, value=title_number)
                        stats_ws.cell(row=stats_row, column=3, value=results_number)
                        stats_ws.cell(row=stats_row, column=4, value=first_table_number)
                        
                        # 设置单元格对齐
                        for col in range(1, 5):
                            stats_ws.cell(row=stats_row, column=col).alignment = Alignment(horizontal='left', vertical='center', wrapText=True)
                        stats_row += 1

            # 遍历第一个表格的命令，查找并比对作用
            for command, original_action in first_table_data:
                excel_action = find_command_action(excel_path, command)
                colored_command = f"\033[33m{command}\033[0m"

                if (not original_action.strip() and excel_action and excel_action != "未找到该命令的作用") or \
                        (excel_action and original_action.replace(" ", "") != excel_action):
                    print(f"命令 {colored_command} 的作用不一致:")
                    print(f"摘要表中的作用: {original_action if original_action.strip() else '[空]'}")
                    print(f"详细描述中的作用: {excel_action}")
                    print("-" * 50)

                    # 如果需要导出Excel，记录不一致的结果
                    if export_excel:
                        result_ws.cell(row=row_index, column=1, value=filepath)
                        result_ws.cell(row=row_index, column=2, value=command)
                        result_ws.cell(row=row_index, column=3, value=excel_action)
                        result_ws.cell(row=row_index, column=4, value=original_action)
                        row_index += 1

        except Exception as e:
            print(f"处理文件 {filepath} 时出错：{str(e)}")
            import traceback
            print(traceback.format_exc())

    # 将保存结果的代码移到循环外，并移除 row_index > 2 的条件
    if export_excel:  # 只保留导出Excel的条件
        try:
            if is_folder:
                first_file = filepaths[0]
                parent_dir = os.path.dirname(os.path.dirname(os.path.dirname(first_file)))
                current_dir_name = os.path.basename(os.path.dirname(os.path.dirname(first_file)))
                result_dir = os.path.join(parent_dir, f"{current_dir_name}-检查结果")
                os.makedirs(result_dir, exist_ok=True)
                result_path = os.path.join(result_dir, "命令比对结果.xlsx")
            else:
                result_path = os.path.join(os.path.dirname(filepaths[0]), "命令比对结果.xlsx")

            result_wb.save(result_path)
            print(f"\n命令比对结果已保存至: {result_path}")
        except Exception as e:
            print(f"保存比对结果时出错：{str(e)}")
            import traceback
            print(traceback.format_exc())

    print("程序执行完成!!!")


def find_command_action(excel_path, target_command):
    try:
        wb = openpyxl.load_workbook(excel_path)
        ws = wb.active

        # 用于记录每个命令已经使用过的行号
        if not hasattr(find_command_action, 'used_rows'):
            find_command_action.used_rows = {}

        # 去除目标命令中的所有空格
        target_command = target_command.replace(" ", "")

        # 获取所有匹配的行号
        matching_rows = []
        for row in range(1, ws.max_row + 1):
            command = ws.cell(row=row, column=1).value
            if command and command.strip().replace(" ", "") == target_command:
                matching_rows.append(row)

        # 如果找到匹配的行
        if matching_rows:
            # 获取该命令已使用的行数
            used_count = find_command_action.used_rows.get(target_command, 0)

            # 如果还有未使用的行
            if used_count < len(matching_rows):
                # 获取下一个未使用的行
                row = matching_rows[used_count]
                action = ws.cell(row=row, column=2).value

                # 更新已使用的行数
                find_command_action.used_rows[target_command] = used_count + 1

                return action.replace(" ", "") if action else None

        return "未找到该命令的作用"

    except Exception as e:
        print(f"查找命令时出错：{str(e)}")
        return None
    finally:
        if 'wb' in locals():
            wb.close()


# 使用示例：
# excel_path = "path/to/your/excel.xlsx"
# command = "banner login"
# action = find_command_action(excel_path, command)
# print(f"命令 {command} 的作用是：{action}")


if __name__ == '__main__':
    table(True, False)
